import moment from 'moment';

/**
 * 时间格式化工具函数
 *
 * 使用示例：
 *
 * // 基础时间格式化
 * formatTime(1640995200000) // "2022-01-01 08:00:00"
 * formatTime(new Date()) // "2024-01-15 14:30:25"
 * formatTime('2022-01-01') // "2022-01-01 00:00:00"
 *
 * // 自定义格式
 * formatTime(1640995200000, 'YYYY/MM/DD') // "2022/01/01"
 * formatTime(1640995200000, 'MM-DD HH:mm') // "01-01 08:00"
 *
 * // 其他格式化函数
 * formatDate(1640995200000) // "2022-01-01"
 * formatTimeOnly(1640995200000) // "08:00:00"
 * formatDateTime(1640995200000) // "01-01 08:00"
 * formatTimeCN(1640995200000) // "2022年01月01日 08:00:00"
 *
 * // 相对时间和判断
 * getRelativeTime(Date.now() - 3600000) // "1小时前"
 * isToday(new Date()) // true
 * isThisWeek(Date.now() - 86400000) // true
 *
 * // 时长计算
 * getDuration('2022-01-01 08:00:00', '2022-01-01 10:30:00') // 150 (分钟)
 * formatDuration('2022-01-01 08:00:00', '2022-01-01 10:30:00') // "2小时30分钟"
 */

/**
 * 格式化时间戳为标准日期时间格式
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @param format 格式化模板，默认为 'YYYY-MM-DD HH:mm:ss'
 * @returns 格式化后的时间字符串
 */
export const formatTime = (
	timestamp: string | number | Date,
	format = 'YYYY-MM-DD HH:mm:ss'
): string => {
	if (!timestamp) return '-';
	return moment(timestamp).format(format);
};

/**
 * 格式化时间戳为日期格式（年-月-日）
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 格式化后的日期字符串
 */
export const formatDate = (timestamp: string | number | Date): string => {
	return formatTime(timestamp, 'YYYY-MM-DD');
};

/**
 * 格式化时间戳为时间格式（时:分:秒）
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 格式化后的时间字符串
 */
export const formatTimeOnly = (timestamp: string | number | Date): string => {
	return formatTime(timestamp, 'HH:mm:ss');
};

/**
 * 格式化时间戳为短日期时间格式
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 格式化后的时间字符串
 */
export const formatDateTime = (timestamp: string | number | Date): string => {
	return formatTime(timestamp, 'MM-DD HH:mm');
};

/**
 * 格式化时间戳为中文日期时间格式
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 格式化后的时间字符串
 */
export const formatTimeCN = (timestamp: string | number | Date): string => {
	return formatTime(timestamp, 'YYYY年MM月DD日 HH:mm:ss');
};

/**
 * 获取相对时间（如：1小时前、3天前等）
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 相对时间字符串
 */
export const getRelativeTime = (timestamp: string | number | Date): string => {
	if (!timestamp) return '-';
	return moment(timestamp).fromNow();
};

/**
 * 判断是否是今天
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 是否是今天
 */
export const isToday = (timestamp: string | number | Date): boolean => {
	if (!timestamp) return false;
	return moment(timestamp).isSame(moment(), 'day');
};

/**
 * 判断是否是本周
 * @param timestamp 时间戳（毫秒）或日期字符串
 * @returns 是否是本周
 */
export const isThisWeek = (timestamp: string | number | Date): boolean => {
	if (!timestamp) return false;
	return moment(timestamp).isSame(moment(), 'week');
};

/**
 * 获取两个时间之间的时长
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param unit 单位（'days', 'hours', 'minutes', 'seconds'）
 * @returns 时长数值
 */
export const getDuration = (
	startTime: string | number | Date,
	endTime: string | number | Date,
	unit: 'days' | 'hours' | 'minutes' | 'seconds' = 'minutes'
): number => {
	if (!startTime || !endTime) return 0;
	const start = moment(startTime);
	const end = moment(endTime);
	return end.diff(start, unit);
};

/**
 * 格式化时长为可读格式
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @returns 格式化的时长字符串（如：2小时30分钟）
 */
export const formatDuration = (
	startTime: string | number | Date,
	endTime: string | number | Date
): string => {
	if (!startTime || !endTime) return '-';

	const start = moment(startTime);
	const end = moment(endTime);
	const duration = moment.duration(end.diff(start));

	const days = Math.floor(duration.asDays());
	const hours = duration.hours();
	const minutes = duration.minutes();
	const seconds = duration.seconds();

	let result = '';
	if (days > 0) result += `${days}天`;
	if (hours > 0) result += `${hours}小时`;
	if (minutes > 0) result += `${minutes}分钟`;
	if (seconds > 0) result += `${seconds}秒`;

	return result || '0秒';
};

// 秒转转化为 *天*小时*分钟*秒
export const formatSecToStr = (seconds: number): string => {
	const daySec = 24 * 60 * 60;
	const hourSec = 60 * 60;
	const minuteSec = 60;
	const dd = Math.floor(seconds / daySec);
	const hh = Math.floor((seconds % daySec) / hourSec);
	const mm = Math.floor((seconds % hourSec) / minuteSec);
	const ss = seconds % minuteSec;
	if (dd > 0) {
		return `${dd}天${hh}小时${mm}分钟${ss}秒`;
	}
	if (hh > 0) {
		return `${hh}小时${mm}分钟`;
	}
	if (mm > 0) {
		return `${mm}分钟${ss}秒`;
	}
	return `${ss}秒`;
};

// 获取分值，0分也算有分值，没有分值返回--
export const getScore = (score: number | null | undefined): string => {
	if (score === null || score === undefined || typeof score !== 'number' || !isFinite(score)) {
		return '--';
	}

	if (Number.isInteger(score)) {
		return score + '分';
	}

	return score.toFixed(2) + '分';
};

/**
 * @description: 秒转时分秒
 * @param {int} value 秒
 * @return {string} 时分秒
 */
export const formatSeconds = (value: number): string => {
	let secondTime = value; // 秒
	let minuteTime = 0; // 分
	let hourTime = 0; // 小时
	if (secondTime >= 60) {
		minuteTime = Math.floor(secondTime / 60);
		secondTime = secondTime % 60;
		if (minuteTime >= 60) {
			hourTime = Math.floor(minuteTime / 60);
			minuteTime = minuteTime % 60;
		}
	}
	let result = `${secondTime < 10 ? `0${Math.floor(secondTime)}` : Math.floor(secondTime)}`;

	result = `${minuteTime < 10 ? `0${minuteTime}` : minuteTime}:${result}`;
	result = `${hourTime < 10 ? `0${hourTime}` : hourTime}:${result}`;
	return result;
};

/**
 * 数组小数位保留方法，确保各项之和等于指定总和
 * @param {Array<number>} arr - 原始数组
 * @param {number} decimal - 保留小数位数
 * @param {number} targetSum - 目标总和
 * @param {number} [adjustIndex] - 可选，指定进行差值调整的数组索引，如果不传或该项为0则默认调整最后一个非零项
 * @returns {Array<number>} 处理后的数组
 *
 * 示例:
 * roundArrayWithSum([2.4,3.4,2.1,2.1], 0, 10) => [2,3,2,3]
 * roundArrayWithSum([2.4,5.4,2.2,0], 0, 10) => [2,5,3,0]
 * roundArrayWithSum([2.4,3.4,2.1,2.1], 0, 10, 1) => [2,4,2,2] (调整索引1的项)
 */
export const roundArrayWithSum = (
	arr: number[],
	decimal: number,
	targetSum: number,
	adjustIndex?: number
): (number | null)[] => {
	// 参数验证
	if (!Array.isArray(arr) || arr.length === 0) {
		return [];
	}

	// 将所有数字按指定小数位进行四舍五入
	const roundedArr = arr.map((num) => (Number.isFinite(num) ? Number(num.toFixed(decimal)) : null));

	// 计算当前总和
	const currentSum = roundedArr.reduce((sum: number, num: number | null) => sum + (num || 0), 0);

	// 如果当前总和已经等于目标总和，直接返回
	if (currentSum === targetSum) {
		return roundedArr;
	}

	// 计算差值
	const difference = Number((targetSum - currentSum).toFixed(decimal));

	// 确定要调整的索引
	let targetAdjustIndex = -1;

	// 如果指定了adjustIndex且该项不为0，使用指定的索引
	if (
		adjustIndex !== undefined &&
		adjustIndex >= 0 &&
		adjustIndex < roundedArr.length &&
		roundedArr[adjustIndex]
	) {
		targetAdjustIndex = adjustIndex;
	} else {
		// 否则找到最后一个非零/非null项的索引（从后往前找）
		for (let i = roundedArr.length - 1; i >= 0; i--) {
			if (roundedArr[i]) {
				targetAdjustIndex = i;
				break;
			}
		}
	}

	// 如果找到了非零/非null项，调整该项的值
	if (targetAdjustIndex !== -1) {
		roundedArr[targetAdjustIndex] = Number(
			((roundedArr[targetAdjustIndex] || 0) + difference).toFixed(decimal)
		);
	}
	// 如果所有项都为0，直接返回原数组（不进行任何调整）

	return roundedArr;
};

// 判断一个字符串是否是JSON字符串，如果是返回json，不是返回false
export const isJSONString = (str: string): Record<string, unknown> | unknown[] | false => {
	try {
		const json = JSON.parse(str);
		if (typeof json === 'object' && json !== null) {
			return json;
		}
		return false;
	} catch {
		return false;
	}
};
